export interface FileUnitType {
    size: number,
    unit: string
}

export const FileUnit: Record<string, FileUnitType> = {
    B: {
        size: 1,
        unit: "B",
    },
    KB: {
        size: 2 ** 10,
        unit: "KB",
    },
    MB: {
        size: 2 ** (10 * 2),
        unit: "MB",
    },
    GB: {
        size: 2 ** (10 * 3),
        unit: "GB",
    },
    TB: {
        size: 2 ** (10 * 4),
        unit: "TB",
    },
    PB: {
        size: 2 ** (10 * 5),
        unit: "PB",
    },
    EB: {
        size: 2 ** (10 * 6),
        unit: "EB",
    },
    ZB: {
        size: 2 ** (10 * 7),
        unit: "ZB",
    },
    YB: {
        size: 2 ** (10 * 8),
        unit: "YB",
    },
    DB: {
        size: 2 ** (10 * 9),
        unit: "DB",
    },
    NB: {
        size: 2 ** (10 * 10),
        unit: "NB",
    },
}

export function convertToFileSizeWithUnit(anySize:string, defaultUnit:FileUnitType = FileUnit.B){
    let units = Object.values(FileUnit).map(item=>item.unit)
    units = units.concat(Object.values(FileUnit).slice(1).map(item=>item.unit.replace("B","")))
    let unitsReg = units.toString().replace(/,/g,"|")
    let reg = new RegExp(`^(\\d+\\.?\\d*)(\\s*(${unitsReg})?)?$`,"i")

    let matchResult = anySize.match(reg)
    if(!matchResult){
        return "未知大小"
    } else {
        if(!matchResult[3]){
            return bytesToSizeWithUnit(Number(matchResult[1]))
        } else {
            return calcSize(Number(matchResult[1]), defaultUnit)
        }
    }
}

export function bytesToSizeWithUnit(byteSize:number){
    let targetUnitIndex = Object.values(FileUnit).findIndex(item => item.size > byteSize) || 0
    let targetUnit:FileUnitType
    if(targetUnitIndex > 0){
        targetUnit = Object.values(FileUnit)[targetUnitIndex - 1]
    } else {
        targetUnit = Object.values(FileUnit)[targetUnitIndex]
    }
    return `${calcSize(byteSize,targetUnit)} ${targetUnit.unit}`
}

export function calcSize(byteSize:number,targetUnit:FileUnitType){
    return Number((byteSize / targetUnit.size).toFixed(2))
}